
import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_player/video_player.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:yun/entity/id_reader_entity.dart';
import 'package:yun/event/change_mode_event.dart';
import 'package:yun/event/download_url_event.dart';
import 'package:yun/event/open_door_event.dart';
import 'package:yun/event/start_read_block_event.dart';
import 'package:yun/event/voice_change_event.dart';
import 'package:yun/http/http_helper.dart';
import 'package:yun/page/setting_common.dart';

import '../entity/cpu_reader_entity.dart';
import '../entity/current_task_entity.dart';
import '../event/check_status_event.dart';
import '../event/door_status_event.dart';
import '../event/inventory_event.dart';
import '../event/read_block_event.dart';
import '../event/start_inventory_event.dart';
import '../log/logger.dart';
import '../main.dart';
import '../mqtt/mqtt.dart';
import '../serial/inventory_manager.dart';
import '../serial/send_helper.dart';

class Index extends StatefulWidget {
  const Index({Key? key}) : super(key: key);

  @override
  State<Index> createState() => _IndexState();
}

class _IndexState extends State<Index> {

  final List<String> bannerList = [];


  StreamSubscription? inventorySubscription;
  StreamSubscription? startInventorySubscription;
  StreamSubscription? startReadBlockSubscription;
  StreamSubscription? readBlockSubscription;
  StreamSubscription? openDoorSubscription;
  StreamSubscription? doorStatusSubscription;
  StreamSubscription? downloadUrlSubscription;
  StreamSubscription? checkStatusSubscription;
  StreamSubscription? changeModeSubscription;
  StreamSubscription? voiceChangeSubscription;
  // List<String> block = [];

  VideoPlayerController? videoPlayerController;

  RxInt currentIndex = 0.obs;
  int index = 0;
  RxBool isPlaying = false.obs;

  WebViewController? webViewController;

  RxInt mode = 3.obs;

  bool openDoorSuccess = false;

  InventoryManager inventoryManager = InventoryManager();

  @override
  initState()  {
    super.initState();


    startInventorySubscription = eventFactory.on<StartInventoryEvent>().listen((event) async {
      // inventoryTime = event.inventoryTime??settingEntity.scanTime??1;
      inventoryManager.startInventory(settingEntity.count??4);
      // hfSerialPortHelper.sendData(inventory());
      // _startInventory();
    });

    changeModeSubscription = eventFactory.on<ChangeModeEvent>().listen((event) async {
      if(settingEntity.mode == 1){
        await videoPlayerController?.setVolume(0);
      }
      _setMode();
    });

    voiceChangeSubscription = eventFactory.on<VoiceChangeEvent>().listen((event) async {
      if(videoPlayerController != null){
        videoPlayerController!.setVolume(event.vol);
      }
    });

    checkStatusSubscription = eventFactory.on<CheckStatusEvent>().listen((event) async {
      if(currentTask.uuids[Task.checkStatus] != null){
        mqttHelper.push(sendStatus(uuid: currentTask.uuids[Task.checkStatus],
          trade_no: currentTask.tradeNos[Task.checkStatus],light1: event.light1==true?1:0, light2: event.light2==true?1:0, door: event.door==true?1:0,));
      }else{
        mqttHelper.push(sendStatusSelf(light1: event.light1==true?1:0, light2: event.light2==true?1:0, door: event.door==true?1:0,));
      }
      currentTask.uuids.remove(Task.checkStatus);
      currentTask.tradeNos.remove(Task.checkStatus);
    });

    startReadBlockSubscription = eventFactory.on<StartReadBlockEvent>().listen((event) async {
      // readBlockInt = 1;
      inventoryManager.addRfid(currentTask.remarks[Task.readBlockData]);
      // block.add(currentTask.remarks[Task.readBlockData]);
      // _readBlock();
    });

    readBlockSubscription = eventFactory.on<ReadBlockEvent>().listen((event) {
      var rfid = event.data.$1;
      var no = event.data.$2;
      if(rfid != null ){

        mqttHelper.push(sendBlock(uuid: currentTask.uuids[rfid], trade_no: currentTask.tradeNos[rfid], block:no??'', rfid: rfid,));
      }
    });

    openDoorSubscription = eventFactory.on<OpenDoorEvent>().listen((event) async {
      openDoorSuccess = false;
      hfSerialPortHelper.sendData(openDoor());
      Future.delayed(const Duration(seconds: 3),(){
        if(!openDoorSuccess){
          mqttHelper.push(sendOpenDoor(uuid: currentTask.uuids[Task.door],
            trade_no: currentTask.tradeNos[Task.door], state: 0,));
        }
      });
    });

    doorStatusSubscription = eventFactory.on<DoorStatusEvent>().listen((event) {
      if(event.isOpen){
        openDoorSuccess = true;
        mqttHelper.push(sendOpenDoor(uuid: currentTask.uuids[Task.door],
          trade_no: currentTask.tradeNos[Task.door], state: 1,));
      }else{
        if(currentTask.uuids.containsKey(Task.door)){
          mqttHelper.push(sendCloseDoor(uuid: currentTask.uuids[Task.door],
            trade_no: currentTask.tradeNos[Task.door], state: 1,));
          currentTask.uuids[Task.inventory] = currentTask.uuids[Task.door];
          currentTask.tradeNos[Task.inventory] = currentTask.tradeNos[Task.door];
          currentTask.remarks[Task.inventoryState] = 1;
          currentTask.uuids.remove(Task.door);
          currentTask.tradeNos.remove(Task.door);
          // inventoryTime = settingEntity.scanTime??1;
          hfSerialPortHelper.sendData(inventory());
        }else{
          mqttHelper.push(sendCloseDoor(uuid: '', trade_no: '', state: 1,));
        }
      }
    });

    inventorySubscription = eventFactory.on<InventoryEvent>().listen((event) async {
        print('Set : ${event.data.length}');
        if(currentTask.uuids[Task.inventory] != null){
          var list = [];
          event.data.toList().forEach((element) {
            list.add(element);
          });
          mqttHelper.push(inventoryRfid(cmd:currentTask.remarks[Task.cmd]??'101003',state:currentTask.remarks[Task.inventoryState]??'1',
            uuid: currentTask.uuids[Task.inventory],
            trade_no: currentTask.tradeNos[Task.inventory],
            rfid: list,));
          currentTask.uuids.remove(Task.inventory);
          currentTask.tradeNos.remove(Task.inventory);
          currentTask.remarks.remove(Task.inventoryState);
          currentTask.remarks.remove(Task.cmd);
        }
    });

    downloadUrlSubscription = eventFactory.on<DownloadUrlEvent>().listen((event) async {
      mqttHelper.push(sendDownload(uuid: currentTask.uuids[Task.downloadUrl], trade_no: currentTask.tradeNos[Task.downloadUrl]));
      var td = await getExternalStorageDirectory();
      String directoryPath = '${td!.path}/img';
      mode.value = 3;
      _stop();
      await deleteFilesInDirectory(directoryPath);

      for (var element in currentTask.urls) {
        await HttpHelper.instance.downLoad(element);
        mqttHelper.push(sendDownloadSuccess(url: element));
      }
      mode.value = 0;
      _loadBanner();
    });

    hideBar();
    _setMode();

    Future.delayed(const Duration(seconds: 3),() {
      _initReader();
    });

    const MethodChannel('toFlutter').setMethodCallHandler(flutterMethod);
  }

  Future flutterMethod(MethodCall methodCall) async{
    switch (methodCall.method) {
      case 'idData':
        print(methodCall.arguments);
        String msg = methodCall.arguments;
        var list = msg.split('|');
        var entity = IdReaderEntity()
          ..name = list[0]
          ..sex = list[1]
          ..nation = list[2]
          ..birthday = list[3]
          ..address = list[4]
          ..id = list[5]
          ..office = list[6]
          ..startTime = list[7]
          ..endTime = list[8];
        mqttHelper.push(sendIdReader(entity: entity));

        break;
      case 'cpuData':
        print(methodCall.arguments);
        String msg = methodCall.arguments;
        var list = msg.split('|');
        var entity = CpuReaderEntity()
          ..data = msg
          ..name = list[8]
          ..sSNum = list[7]
          ..cardNum = list[6]
          ..issuingDate = list[4]
          // ..terminalNum =
          // ..cardResetInfo =
          // ..terminalDeviceNum =
          // ..administrativeDivisionCodeOfIssuingArea = list[11]
          ..expirationDate = list[5]
          ..cardCanonicalVersion = list[2]
          ..cardIdentificationCode = list[0];
        mqttHelper.push(sendCpuReader(entity:entity));

        break;
    }
  }

  _initReader() async {
    await const MethodChannel('toAndroid').invokeMethod('openDev');
  }


  Future deleteFilesInDirectory(String directoryPath) async {
    final directory = Directory(directoryPath);
    if (await directory.exists()) {
      final List<FileSystemEntity> files = directory.listSync();
      for (final file in files) {
        if (file is File) {
          await file.delete();
        }
      }
    }
  }

  _setMode() async {
    mode.value = settingEntity.mode??0;
    // if(mode.value == 0){
    //   mode.value = 1;
    // }else{
    //   mode.value = 0;
    // }
    if(mode.value == 0){
      _loadBanner();
    }
    if(mode.value == 1){
      _stop();
    }
  }

  _stop() async {
    _timer?.cancel();
    _timer = null;
    isPlaying.value = false;
    // currentIndex.value = 0;
    // index = 0;
    await videoPlayerController?.pause();
    await videoPlayerController?.dispose();
  }


  Future _loadBanner() async {

    try{
      final directory = await getExternalStorageDirectory();
      final directoryPath = '${directory!.path}/img';

      final directoryList = Directory(directoryPath);
      final fileList = directoryList.list();
      bannerList.clear();
      await for (final fileEntity in fileList) {
        final fileName = fileEntity.uri.toString().split('/').last;
        bannerList.add('$directoryPath/$fileName');
      }
      setState(() {

      });
      _startAutoPlay();
    }catch(e){
      print(e);
    }

  }

  _swiper(){
    return Obx(() => SizedBox(
      width: double.infinity,
      height: double.infinity,
      child: Stack(
        children: [
          if(bannerList[currentIndex.value].endsWith('mp4'))...[
            if(isPlaying.value)...[
              VideoPlayer(videoPlayerController!)
            ],
          ],
          if(!bannerList[currentIndex.value].endsWith('mp4'))...[
             Image.file(File(bannerList[currentIndex.value]), width:double.infinity,fit: BoxFit.cover,)
          ],
        ],
      )
    ));
  }

   _load() async {
     isPlaying.value = true;
     if(videoPlayerController != null){
      print('videoPlayerController is not dispose');
      // await videoPlayerController?.pause();
      await videoPlayerController?.dispose();
    }
    videoPlayerController = VideoPlayerController.file(File(bannerList[currentIndex.value]), videoPlayerOptions: VideoPlayerOptions(
      mixWithOthers: true,
      allowBackgroundPlayback: false,
    ),);
    await videoPlayerController?.initialize();
    await videoPlayerController?.setVolume(settingEntity.adVolume??0.2);
    await videoPlayerController?.play();
    videoPlayerController?.addListener(() async {
      final int currentPosition = videoPlayerController!.value.position.inSeconds;
      final bool play = videoPlayerController!.value.isPlaying;
      print('curr $currentPosition, isPlaying  = $play');
      if(settingEntity.log??false){
        Logger().write('curr $currentPosition, isPlaying  = $play\r\n');
      }
      if(!play){
        print('Video playing next');
        isPlaying.value = false;
        await videoPlayerController?.dispose();
        _next();
      }
      if(currentPosition == 99 && isPlaying.value){
        print('Video playing next');
        isPlaying.value = false;
        await videoPlayerController?.dispose();
        _next();
      }

    });
  }

  Timer? _timer;
  _startAutoPlay(){
    _timer?.cancel();
    _timer = null;
    _timer = Timer.periodic(const Duration(seconds: 10), (timer) {
      _next();
    });
  }

  _next(){
    if(mode.value != 0){
      return;
    }
    if(!isPlaying.value && bannerList.isNotEmpty){
      index ++;
      currentIndex.value = index%(bannerList.length);
      if(bannerList[currentIndex.value].endsWith('mp4')){
        _load();
      }
    }
  }

  hideBar() async {
    await const MethodChannel('toAndroid').invokeMethod('hideBar');
  }
  showBar() async {
    await const MethodChannel('toAndroid').invokeMethod('showBar');
  }

  @override
  void dispose() {
    checkStatusSubscription?.cancel();
    checkStatusSubscription = null;
    downloadUrlSubscription?.cancel();
    downloadUrlSubscription = null;
    inventorySubscription?.cancel();
    inventorySubscription = null;
    changeModeSubscription?.cancel();
    changeModeSubscription = null;
    voiceChangeSubscription?.cancel();
    voiceChangeSubscription = null;
    startReadBlockSubscription?.cancel();
    startReadBlockSubscription = null;
    startInventorySubscription?.cancel();
    startInventorySubscription = null;
    openDoorSubscription?.cancel();
    openDoorSubscription = null;
    doorStatusSubscription?.cancel();
    doorStatusSubscription = null;
    _timer?.cancel();
    _timer = null;
    videoPlayerController?.dispose();
    hfSerialPortHelper.close();
    mqttHelper.dispose();
    const MethodChannel('toAndroid').invokeMethod('closeDev');
    super.dispose();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        alignment: Alignment.center,
        child: Obx(() => Stack(
          children: [
            // TextField(
            //   keyboardType: TextInputType.none,
            //   decoration:  InputDecoration(
            //     border:  const OutlineInputBorder(),
            //     contentPadding: const EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5).r,
            //   ),
            //   style: TextStyle(fontSize: 8.sp),
            //   onChanged: (value){
            //     print(value);
            //   },
            //   autofocus: true,
            // ),
            Image.asset("assets/images/bg.jpg", width:double.infinity,fit: BoxFit.cover,),
            if(mode.value == 0 && bannerList.isNotEmpty)...[
              _swiper(),
            ],
            if(mode.value == 1)...[
              WebViewWidget(
                  controller: WebViewController()
                    ..setJavaScriptMode(JavaScriptMode.unrestricted)
                    ..loadRequest(Uri.parse(settingEntity.url??'cloudlinks.cn'))
              ),
            ],
            InkWell(
              onTap: () {
                Get.to(()=> const SettingCommon());
              },
              child: SizedBox(height: 100.h,width: 100.w,),
            )
          ],
        ))
      ),
    );
  }


}

